#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
校验模块，包含过滤类和校验类
'''

from lib.webconf import WEBCONF


class Filter(object):
    '字符串过滤类'
    @staticmethod
    def to_unicode(data, encoding=None):
        '转换编码到Unicode'
        import collections
        _encoding = encoding if encoding else WEBCONF['encoding']

        def _convert(data):
            '递归函数定义'
            if isinstance(data, unicode):
                return data
            elif isinstance(data, str):
                return unicode(data, _encoding)
            elif isinstance(data, collections.Mapping):
                return dict(map(_convert, data.iteritems()))
            elif isinstance(data, collections.Iterable):
                return type(data)(map(_convert, data))
            else:
                return data
        return _convert(data)

    @staticmethod
    def to_str(data):
        '递归转化字符串形式'
        import collections

        def _convert(data):
            '递归函数定义'
            if isinstance(data, unicode):
                return data
            elif isinstance(data, str):
                return data
            elif isinstance(data, collections.Mapping):
                return dict(map(_convert, data.iteritems()))
            elif isinstance(data, collections.Iterable):
                return type(data)(map(_convert, data))
            else:
                return str(data)
        return _convert(data)


class Check(object):
    '字符串校验组件'
    @staticmethod
    def is_len_range(len_min, len_max=None):
        '检查长度是否在范围内，长度按字节数计算'
        if not len_max:
            len_max = len_min

        def dec(func):
            '新装饰器'
            def dec_(target_str):
                '新函数'
                if len(target_str) not in xrange(len_min, len_max + 1):
                    return False
                return func(target_str)
            return dec_
        return dec

    @staticmethod
    def is_re_match(pattern_str):
        '检查是否匹配正则表达式'
        def dec(func):
            '新装饰器'
            def dec_(target_str):
                '新函数'
                import re

                encoding = WEBCONF['encoding']
                if not re.search(pattern_str, target_str.decode(encoding)):
                    print target_str
                    return False
                return func(target_str)
            return dec_
        return dec

    @staticmethod
    def is_alnum(is_alpha_first=False):
        '检查是否只有数字和字母，可选是否需要字母开头'
        def dec(func):
            '新装饰器'
            def dec_(target_str):
                '新函数'
                if not target_str.isalnum():
                    return False
                if is_alpha_first and not target_str[0].isalpha():
                    return False
                return func(target_str)
            return dec_
        return dec

    @staticmethod
    def is_digit(is_nonzero_first=False):
        '检查是否只有数字，可选是否需要非零开头'
        def dec(func):
            '新装饰器'
            def dec_(target_str):
                '新函数'
                if not target_str.isdigit():
                    return False
                if is_nonzero_first and target_str[0] == '0':
                    return False
                return func(target_str)
            return dec_
        return dec

    @staticmethod
    def is_date(format_str):
        '检查日期是否符合格式'
        def dec(func):
            '新装饰器'
            def dec_(target_str):
                '新函数'
                import time
                try:
                    time_tuple = time.strptime(target_str, format_str)
                except(ValueError):
                    return False
                return func(target_str)
            return dec_
        return dec

    @staticmethod
    def is_empty(func):
        '检查是否为空，如果为空直接返回True'
        def dec(target_str):
            '新函数'
            if target_str == '':
                return True
            return func(target_str)
        return dec


class CheckMethodError(AttributeError):
    '定义了没有找到对应的校验方法时的错误'
    pass


class Validator(object):
    '字符串检查类'

    @classmethod
    def check(cls, target_str, type_key):
        '检查字符串是否符合预想的类型'
        if not isinstance(target_str, str):
            return False

        check_key = 'check_' + type_key
        if not hasattr(cls, check_key):
            raise CheckMethodError('%s is not defined.' % check_key)

        func = getattr(cls, check_key)
        return func(target_str)

    @classmethod
    def check_from_dict(cls, target_dict, check_list):
        '从传入的字典挑选出需要的字段并进行检验'
        checked_dict = {}
        for key in check_list:
            value = target_dict.get(key, '')
            if not cls.check(value, key):
                return {}, key
            checked_dict[key] = value
        return checked_dict, None
